home *** CD-ROM | disk | FTP | other *** search
- COMMENT ~
- BCD.ASM -- BCD Conversion Routines
-
- From `BLUEBOOK of ASSEMBLY ROUTINES for the IBM PC & XT'
- by Christopher L. Morgan
- Copyright (C) 1984 by The Waite Group, Inc.
-
- >>>>> See BCD.DOC for complete descriptions of routines. <<<<<
- _____________________________________________________________________________
-
- Contents:
- ---------
- BCDIN -- Convert from ASCII Decimal to BCD
- BCDOUT -- Convert from BCD to ASCII Decimal
- BCD2I16 -- Convert from BCD to 16-bit Binary
- I162BCD -- Convert from 16-bit Binary to BCD
- _____________________________________________________________________________
- ~
- EXTRN STDIN:FAR,STDOUT:FAR
- ;_____________________________________________________________________________
- ;
- DATAS SEGMENT PUBLIC
- BCDBUFF DB 18 DUP(?)
- DATAS ENDS
- ;_____________________________________________________________________________
- ;
- CODES SEGMENT
- PUBLIC BCDIN,BCDOUT,BCD2I16,I162BCD
- ASSUME CS:CODES,DS:DATAS
- ;______________________________ BCD ROUTINES _________________________________
- ;Routine to convert from ASCII decimal to internal BCD format.
- ;
- BCDIN PROC FAR
-
- PUSH DS ;Save registers
- PUSH DI
- PUSH DX
- PUSH CX
- PUSH AX
- ;
- ;Set up data segment
- MOV DX,DATAS ;Point to data segment
- MOV DS,AX
- ;
- ;Clear BCD buffer
- LEA DI,BCDBUFF ;Point to BCD buffer
- MOV AL,0 ;zero byte
- MOV CX,18 ;buffer SIze
- BCDIN1:
- MOV [DI],AL ;zero the byte
- INC DI ;Point to next byte
- LOOP BCDIN1
- BCDIN2:
- ;
- ; get the digit
- CALL STDIN ;Digit comes in AL
- SUB AL,30H ;Subract 30H
- JL BCDIN4 ;Check if too low
- CMP AL,9
- JG BCDIN4 ;Check if too high
- ;
- ;Multiply buffer by 10 and add new digit
- LEA DI,BCDBUFF ;Point to BCD buffer
- MOV CX,18 ;buffer SIze
- BCDIN3:
- PUSH CX ;Save counter
- MOV DL,AL ;Save previous digit
- MOV AL,[DI] ;Pick up byte from buffer
- MOV CL,4 ;for a count of 4
- SAL AX,CL ;Shift byte left
- OR AL,DL ;Combine with previous digit
- MOV [DI],AL ;Result goes back
- MOV AL,AH ;Prepare for next byte
- AND AL,0FH ;Strip to byte
- INC DI ;Point to next byte
- POP CX ;Restore count
- LOOP BCDIN3
- JMP BCDIN2
- BCDIN4:
- POP AX ;Restore registers
- POP CX
- POP DX
- POP DI
- POP DS
- RET ;Return
- BCDIN ENDP
- ;------------------------------------------------------------------------------
- ;Routine to convert from internal BCD to ASCII decimal
- ;
- BCDOUT PROC FAR
- PUSH DS ;Save registers
- PUSH SI
- PUSH DX
- PUSH CX
- PUSH AX
- ;
- ;Set up data segment
- MOV AX,DATAS ;Point to data segment
- MOV DS,AX
- MOV CX,18 ;for a count of 18
- LEA SI,BCDBUFF ;Point ot BCD buffer
- ADD SI,17 ;Point ot end of BCD buffer
- MOV DH,0 ;Clear flag for leading zeros
- BCDOUT1:
- PUSH CX ;Save loop count
- MOV AL,[SI] ;get BCD byte
- DEC SI ;And point to next
- MOV DL,AL ;Save it
- ;
- ;Upper digit
- MOV CL,4 ;for a count of 4
- ROL AL,CL ; rotate byte
- AND AL,0FH ;just the digit
- OR DH,AL ;Leading zeros
- JZ BCDOUT2 ;if so skip digit
- ADD AL,30H ;make ASCII
- CALL STDOUT ;Send it out
- BCDOUT2:
- POP CX ;Restore count
- CMP CX,1 ;Last digit ?
- JNZ BCDOUT3 ;Skip in not
- MOV DH,0FFH ; set flag if so
- BCDOUT3:
- PUSH CX ;Save count
- MOV AL,DL ;byte back
- ;
- ;Lower digit
- AND AL,0FH ;just the digit
- OR DH,AL ;Leading zeros ?
- JZ BCDOUT4 ;if so skip digit
- ADD AL,30H ;make ASCII
- CALL STDOUT ;Send it out
- BCDOUT4:
- POP CX ;Restore loop count
- LOOP BCDOUT1
- POP AX ;Restore registers
- POP CX
- POP DX
- POP SI
- POP DS
- RET ;Return
- BCDOUT ENDP
- ;------------------------------------------------------------------------------
- ;Routine to convert from internal BCD to internal 16-bit binary.
- ;
- BCD2I16 PROC FAR
- PUSH DS ;Save registers
- PUSH SI
- PUSH CX
- PUSH AX
- ;
- ;Set up data segment
- MOV AX,DATAS ;Point of data segment
- MOV DS,AX
- ;
- ;Set up loop
- MOV CX,18 ;initialize counter
- LEA SI,BCDBUFF ;Point to buffer
- ADD SI,17 ;Point to end of BCD buffer
- MOV DX,0 ;Set DX to zero
- BCD2I161:
- PUSH CX ;Save loop count
- MOV AL,[SI] ;get BCD byte
- DEC SI ;And point to next
- MOV BL,AL ;Save it
- ;
- ;Upper digit
- MOV CL,4 ;for a count of 4
- ROL AL,CL ; rotate byte
- AND AL,0FH ;just the digit
- CBW
- PUSH AX ;Save digit
- MOV AX,DX
- MOV CX,10 ;multiplier of 10
- MUL CX ;multiply
- MOV DX,AX ;Result in DX
- POP AX ;Restore digit
- ADD DX,AX ;Add in digit
- MOV AL,BL ;byte back
- ;
- ;Lower digit
- AND AL,0FH ;just digit
- CBW
- PUSH AX ;Save digit
- MOV AX,DX
- MOV CX,10 ;miltiplier of 10
- MUL CX ;multiply
- MOV DX,AX ;Result in DX
- POP AX ;Restore digit
- ADD DX,AX ;Add in digit
- POP CX ;Restore loop count
- LOOP BCD2I161
- POP AX ;Restore registers
- POP CX
- POP SI
- POP DS
- RET ;Return
- BCD2I16 ENDP
- ;-----------------------------------------------------------------------------
- ;Routine to convert from internal 16-bit binary to internal BCD.
- ;
- I162BCD PROC FAR
- ;
- ;A binary number is in DX
- PUSH DS ;Save registers
- PUSH DI
- PUSH DX
- PUSH CX
- PUSH AX
- ;
- ;Set up data segment
- MOV AX,DATAS ;Point to data segment
- MOV DS,AX
- ;
- ;Clear BCD buffer
- LEA DI,BCDBUFF ;Point to buffer
- MOV AL,0 ;zero byte
- MOV CX,18 ;buffer SIze
- I162BCD1:
- MOV [DI],AL ;Clear byte
- INC DI ;next byte
- LOOP I162BCD1
- ;
- ;Put the digits in a buffer
- LEA DI,BCDBUFF ;Point to buffer
- I162BCD2:
- MOV AX,DX ;numerator
- MOV DX,0 ;Clear upper hALf
- MOV CX,10 ;Divisor of 10
- DIV CX ;Divide
- XCHG AX,DX ;get quotient
- MOV BL,AL ;Save digit
- MOV AX,DX ;numerator
- MOV DX,0 ;Clear upper hALf
- MOV CX,10 ;Divisor of 10
- DIV CX ;Divide
- XCHG AX,DX ;get quotient
- MOV CL,4 ;for a count of 4
- ROL AL,CL ; rotate digit
- AND AL,0F0H ;just the digit
- OR AL,BL ;Combine digits
- MOV [DI],AL ;Put in buffer
- INC DI ;next byte
- CMP DX,0 ;done ?
- JNZ I162BCD2
- POP AX ;Restore registers
- POP CX
- POP DX
- POP DI
- POP DS
- RET ;Return
- I162BCD ENDP
- ;-----------------------------------------------------------------------------
- CODES ENDS
- ;
- END
- ;_____________________________________________________________________________
- ;>>>>> Physical EOF BCD.ASM <<<<<